#define A(i, j) A[(i) + (j) * (LDA)]
#define B(i, j) B[(i) + (j) * (LDB)]
#define C(i, j) C[(i) + (j) * (LDC)]
static void mm_v3_corner(int M, int N, int K, double *A, int LDA, double *B,
                         int LDB, double *C, int LDC) {
    double tmp = 0;
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
            tmp = 0;
            for (int k = 0; k < K; k++) {
                tmp += A(i, k) * B(k, j);
            }
            C(i, j) = tmp;
        }
    }
}
// 重复利用寄存器 2x2分块
// A:[M, K] B:[K, N] C:[M, N]
inline void mm_v3(int M, int N, int K, double *A, int LDA, double *B, int LDB,
                  double *C, int LDC) {
    int m2 = M & -2;
    int n2 = N & -2;
    for (int i = 0; i < m2; i += 2) {
        for (int j = 0; j < n2; j += 2) {
            double c00 = 0;
            double c01 = 0;
            double c10 = 0;
            double c11 = 0;
            for (int k = 0; k < K; k++) {
                double a0 = A(i, k);
                double a1 = A(i + 1, k);
                double b0 = B(k, j);
                double b1 = B(k, j + 1);
                c00 += a0 * b0;
                c01 += a0 * b1;
                c10 += a1 * b0;
                c11 += a1 * b1;
            }
            C(i, j) = c00;
            C(i, j + 1) = c01;
            C(i + 1, j) = c10;
            C(i + 1, j + 1) = c11;
        }
    }
    if (M == m2 && N == n2) {
        return;
    }
    if (M != m2) {
        mm_v3_corner(M - m2, N, K, &A(m2, 0), LDA, &B(0, 0), LDB, &C(m2, 0),
                     LDC);
    }
    if (N != n2) {
        mm_v3_corner(m2, N - n2, K, &A(0, 0), LDA, &B(0, n2), LDB, &C(0, n2),
                     LDC);
    }
}
#undef A
#undef B
#undef C
